package com.gismore.demo.security.tooken;

import com.alibaba.fastjson.JSON;
import com.gismore.demo.config.AppConfig;
import com.google.common.collect.Maps;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.codec.Base64;
import org.joda.time.DateTime;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

/**
 * Created by lei on 17/2/27.
 */
@Slf4j
public class JwtAccessTokenProcessor {
	private static String SALT = "GISMORE_JWT_TOKEN";
	private static final String JWT_ID="jwt";
	private static Long JWT_TTL = AppConfig.me().jwtTTL();

	public JwtAccessTokenProcessor use(final String salt){
		SALT = salt;
		return this;
	}
	/**
	 * 由字符串生成加密key
	 * @return
	 */
	private static SecretKey generalKey(){
		String stringKey = DateTime.now().getDayOfYear()+SALT;
		byte[] encodedKey = Base64.decode(stringKey);
		SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
		return key;
	}
	public static String createJWT(Map<String,Object> subject){
		return create(JWT_ID,JSON.toJSONString(subject), JWT_TTL);
	}
	public static String createJWT(Map<String,Object> subject,Long ttlMillis){
		return create(JWT_ID,JSON.toJSONString(subject),ttlMillis);
	}
	/**
	 * 创建jwt
	 * @param id
	 * @param subject
	 * @param ttlMillis
	 * @return
	 * @throws Exception
	 */
	public static String create(String id, String subject, Long ttlMillis) {
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);
		SecretKey key = generalKey();
		JwtBuilder builder = Jwts.builder()
				.setId(id)
				.setIssuedAt(now)
				.setSubject(subject)
				.signWith(signatureAlgorithm, key);
		if(ttlMillis !=null && ttlMillis>0){
			Long expMillis = nowMillis + ttlMillis;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);
		}
		return builder.compact();
	}

	/**
	 * 解密jwt
	 * @param jwt
	 * @return
	 * @throws Exception
	 */
	public static Properties parse(String jwt){
		SecretKey key = generalKey();
		try {
			Claims claims = Jwts.parser()
					.setSigningKey(key)
					.parseClaimsJws(jwt).getBody();
			return JSON.parseObject(claims.getSubject(),Properties.class);
		}catch (ExpiredJwtException e){
			log.warn("Expired Token => {} ",jwt);
		}catch (SignatureException e){
			log.warn("Signature Failure Token => {}",jwt);
		}catch (Exception e){
			log.warn("Invalid Token => {}",jwt);
		}
		return new Properties();
	}

	public static void main(String[] args) throws Exception{
		Map<String,Object> params = Maps.newHashMap();
		params.put("needLogin",false);
		String jwt = JwtAccessTokenProcessor.createJWT(params);
		System.out.println(jwt);

		Properties properties = JwtAccessTokenProcessor.parse(jwt);
		if(properties != null){
			properties.forEach((k,v)->System.out.println(k+":"+v));
		}
	}
}
